/**
 * Copyright 2010, Lars J. Nilsson <http://www.larsan.net> 
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.larsan.dconf.cli;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import net.larsan.dconf.cli.comm.CreateNode;
import net.larsan.dconf.cli.comm.DeleteNode;
import net.larsan.dconf.cli.comm.Export;
import net.larsan.dconf.cli.comm.Goto;
import net.larsan.dconf.cli.comm.CreateDomain;
import net.larsan.dconf.cli.comm.DeleteDomain;
import net.larsan.dconf.cli.comm.Exit;
import net.larsan.dconf.cli.comm.Help;
import net.larsan.dconf.cli.comm.Import;
import net.larsan.dconf.cli.comm.ListDomains;
import net.larsan.dconf.cli.comm.ListNode;
import net.larsan.dconf.cli.comm.Remove;
import net.larsan.dconf.cli.comm.Set;

@Singleton
public class CommandRegistryImpl implements CommandRegistry {

	private final Map<String, Command> comms = new HashMap<String, Command>();
	
	@Inject
	public CommandRegistryImpl(
				Goto gt,
				Exit e,
				CreateDomain cd,
				DeleteDomain dd,
				ListDomains ld,
				CreateNode cn,
				DeleteNode dn,
				ListNode ln,
				Remove r,
				Set s,
				Help h,
				Export ex,
				Import im) {
		
		register(dn);
		register(im);
		register(ex);
		register(h);
		register(s);
		register(r);
		register(ln);
		register(cn);
		register(ld);
		register(dd);
		register(cd);
		register(e);
		register(gt);
	}
	
	@Override
	public Collection<Command> getCommands() {
		return comms.values();
	}

	@Override
	public void exec(String[] args) {
		if(args.length > 0 && hasCommand(args[0])) {
			Command c = comms.get(args[0]);
			Options opts = c.getOptions();
			BasicParser p = new BasicParser();
			try {
				CommandLine cl = p.parse(opts, trimCommand(args));
				c.exec(cl);
			} catch (ParseException e) {
				System.err.println("Failed to parse command: " + e.getMessage());
			}
		}
	}

	// --- PRIVATE METHODS --- //

	private String[] trimCommand(String[] args) {
		String[] next = new String[args.length - 1];
		System.arraycopy(args, 1, next, 0, next.length);
		return next;
	}
	
	private boolean hasCommand(String comm) {
		if(comms.containsKey(comm)) {
			return true;
		} else {
			System.err.println("Unknown command: " + comm);
			return false;
		}
	}
	
	private void register(Command c) {
		for (String s : c.getNames()) {
			comms.put(s, c);
		}
	}
}
